package com.jrx.anytxn.reporting.service.impl;

import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.common.uitl.FileUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.customer.dto.customer.CustomerRes;
import com.jrx.anytxn.customer.entity.CmCustomerAddressInfo;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerAddressInfoMapper;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.param.entity.PrCodeTable;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.entity.PrProductTable;
import com.jrx.anytxn.param.service.ntfs.ICreateTskdFileSampleSimple;
import com.jrx.anytxn.param.service.product.IProductTableService;
import com.jrx.anytxn.param.service.system.ICodeTableService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.reporting.constant.ReportingConstant;
import com.jrx.anytxn.reporting.service.ILSPuHuiService;
import com.jrx.anytxn.transaction.bean.DebtBean;
import com.jrx.anytxn.transaction.entity.AmLoanAccountInfo;
import com.jrx.anytxn.transaction.entity.AmLoanMainInfo;
import com.jrx.anytxn.transaction.entity.TlPaymentAllocationLog;
import com.jrx.anytxn.transaction.entity.TlThirdPartyPayment;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmLoanMainInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlPaymentAllocationLogMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlThirdPartyPaymentMapper;
import com.jrx.anytxn.transaction.service.IDebtCalculationService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class LSPuHuiServiceImpl implements ILSPuHuiService {

    private static final Logger logger = LoggerFactory.getLogger(LSPuHuiServiceImpl.class);

    @Autowired
    private ICustomerService customerService;
    @Resource
    private ExtAmLoanMainInfoMapper extAmLoanMainInfoMapper;
    @Autowired
    private IDebtCalculationService debtCalculationService;
    @Autowired
    private IOrganizationTableService organizationTableService;
    @Resource
    private ExtTlThirdPartyPaymentMapper extTlThirdPartyPaymentMapper;
    @Resource
    private ExtTlPaymentAllocationLogMapper extTlPaymentAllocationLogMapper;
    @Resource
    private ExtCmCustomerAddressInfoMapper extCmCustomerAddressInfoMapper;
    @Autowired
    private ICodeTableService codeTableService;
    @Autowired
    private IProductTableService productTableService;
    @Autowired
    private ICreateTskdFileSampleSimple createTskdFileSampleSimple;



    @Override
    public String createBreakContractMessage(AmLoanAccountInfo amLoanAccountInfo) throws TxnBizException {
        if(null == amLoanAccountInfo){
            return null;
        }
        StringBuffer sb = new StringBuffer();

        //机构信息
        PrOrganizationTable org = organizationTableService.findByOrId(amLoanAccountInfo.getOrganizationId(), amLoanAccountInfo.getTenantId());

        //查询客户信息
        CustomerRes customer = customerService.getCustomerByChannelAndCustomerIdAndTensnId(amLoanAccountInfo.getChannel(),
                amLoanAccountInfo.getCustomerId(), amLoanAccountInfo.getTenantId());
        //查询贷款信息表
        AmLoanMainInfo amLoanMainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndCusId(amLoanAccountInfo.getLoanId(), amLoanAccountInfo.getCustomerId(), amLoanAccountInfo.getTenantId());
        //查询产品信息
        PrProductTable prProductTable = productTableService.findProByProIdAndOrgId(amLoanAccountInfo.getProductId(),amLoanAccountInfo.getOrganizationId(),amLoanAccountInfo.getTenantId());

        //查询该笔订单最近的还款流水(查询三方还款流水)
        TlThirdPartyPayment thirdPartyPayment = extTlThirdPartyPaymentMapper.findLastByCustomerIdAndLoanId(amLoanMainInfo.getLoanId(),amLoanMainInfo.getCustomerId(),amLoanMainInfo.getTenantId());

        //地址信息
        CmCustomerAddressInfo cond = new CmCustomerAddressInfo();
        cond.setTenantId(amLoanMainInfo.getTenantId());
        cond.setCustomerId(amLoanMainInfo.getCustomerId());
        cond.setAddressType(ReportingConstant.ADDRESS_TYPE_1);
        List<CmCustomerAddressInfo> addressInfos = extCmCustomerAddressInfoMapper.selectByCondSelective(cond);


        //1 客户id 根据渠道不同，添加前缀 TODO
        sb.append("JLCLOUD" + amLoanAccountInfo.getCustomerId() + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //2 客户名称
        sb.append(customer.getFirstLevel().getChineseName() + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //3 证件类型 2 身份证
        sb.append("2" + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //4 证件号码
        sb.append(customer.getFirstLevel().getIdNumber() + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //5 贷款发放行代码
        sb.append(ReportingConstant.LS_BRANCH_CODE + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //6 贷款合同号
        sb.append("JLCLOUD" + amLoanMainInfo.getContractNumber() + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //7 借据号
        sb.append("JLCLOUD" + amLoanMainInfo.getLoanId() + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //8 业务品种类型 6-消费贷款，7-个人经营性贷款
        if(ReportingConstant.LOAN_TYPE_6.equals(prProductTable.getTableType())){
            sb.append("7" + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        }else{
            sb.append("6" + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        }

        //9 主要担保方式 1-保证
        sb.append("1" + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //10 发放金额
        sb.append(amLoanMainInfo.getLoanAmount() + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //11 贷款余额 = 剩余本金？
        sb.append(amLoanAccountInfo.getRemainPrincipal() + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //12 发放日期
        String putoutDate = DateUtils.format(amLoanMainInfo.getPostingDate(),DateUtils.DATE_PATTERN);
        sb.append(putoutDate + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //13 实际到期日
        String actualMaturity = DateUtils.format(amLoanMainInfo.getLastPaymentDate(),DateUtils.DATE_PATTERN);
        sb.append(actualMaturity + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //14 违约金额
        DebtBean debtBean = debtCalculationService.getBalance(amLoanAccountInfo, org.getNextProcessingDate(), true, null, null, false);
        sb.append(debtBean.getTotalAmount() + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //15 违约天数
        sb.append(amLoanAccountInfo.getDelqDays() + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //16 五级分类结果
        sb.append(transFive(amLoanAccountInfo.getLoanClassify()) + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //17 还本方式
        String paymentMode="";
        switch (amLoanMainInfo.getAmortMethodTableId()){
            case ReportingConstant.PRIN_CHARGE_OPTION_MONTHLY_INTPAY ://按期付息，到期还本
                paymentMode="6";
                break;
            case ReportingConstant.PRIN_CHARGE_OPTION_INTPAY ://利随本清
                paymentMode="5";
                break;
            default:
                paymentMode="1";
                break;
        }
        sb.append(paymentMode + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);

        BigDecimal lastPayAmt = BigDecimal.ZERO;//最近还款金额
        String lastPayDate = "";//最近还款日期

        if(null != thirdPartyPayment){
            List<TlPaymentAllocationLog> tlPaymentAllocationLogList = extTlPaymentAllocationLogMapper.selectBySeqNoAndTenantId(thirdPartyPayment.getSeqNo(),amLoanMainInfo.getTenantId());
            if(CollectionUtils.isNotEmpty(tlPaymentAllocationLogList)){
                lastPayDate = DateUtils.format(tlPaymentAllocationLogList.get(0).getPostingDate(),DateUtils.DATE_PATTERN_ANOTHER);

                for(TlPaymentAllocationLog log : tlPaymentAllocationLogList){
                    //只取最近一期的
                    if(lastPayDate.equals(DateUtils.format(log.getPostingDate(),DateUtils.DATE_PATTERN_ANOTHER))){
                        lastPayAmt = lastPayAmt.add(log.getPostingAmount());
                    }
                }
            }
        }
        //18 最近一次还款金额
        sb.append(lastPayAmt + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //19 最近一次还款日期
        sb.append(lastPayDate + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //20 客户住址
        String address = "";
        if(CollectionUtils.isNotEmpty(addressInfos)){
            if(!StringUtils.isBlank(addressInfos.get(0).getProvince())){
                PrCodeTable province = codeTableService.findByTypeAndCodeId(ReportingConstant.PROVINCE_TYPE_ID,
                        addressInfos.get(0).getProvince(),addressInfos.get(0).getTenantId());
                if(null != province){
                    address = address + province.getCodeName();
                }
            }
            if(!StringUtils.isBlank(addressInfos.get(0).getCity())){
                PrCodeTable city = codeTableService.findByTypeAndCodeId(ReportingConstant.CITY_TYPE_ID,
                        addressInfos.get(0).getCity(),addressInfos.get(0).getTenantId());
                if(null != city){
                    address = address + city.getCodeName();
                }
            }
            if(!StringUtils.isBlank(addressInfos.get(0).getDistrict())){
                PrCodeTable area = codeTableService.findByTypeAndCodeId(ReportingConstant.AREA_TYPE_ID,
                        addressInfos.get(0).getDistrict(),addressInfos.get(0).getTenantId());
                if(null != area){
                    address = address + area.getCodeName();
                }
            }
            address = address + addressInfos.get(0).getAddress();
        }
        sb.append(address + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //21 住址行政区划代码
        sb.append(customer.getFirstLevel().getIdNumber().substring(0,6) + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //22 客户其他证件类型、客户其他证件号码
        sb.append("" + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //23 共同债务人姓名、证件类型、证件号码
        sb.append("" + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //24 助学贷款专项指标
        sb.append("" + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //25 来源系统
        sb.append("JLCLOUD" + ReportingConstant.LS_BREAK_CONTRACT_SEPARATOR);
        //26 报表日期
        String reportDate = DateUtils.format(org.getToday(),DateUtils.DATE_PATTERN);
        sb.append(reportDate);

        return sb.toString();
    }

    @Override
    public void generateUnionFile(List<String> messageList, String reportingPath,String fileName, String fileType) throws TxnException {
        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(ReportingConstant.DEFAULT_ORG_NUMBER);
        String toDay = DateUtils.format(org.getToday(),"yyyyMMdd");

        String collectionFileName = fileType + "_" + fileName + ".dat";

        String filePath = reportingPath + org.getTenantId() + File.separator + toDay + File.separator;

        Path reportingFile = Paths.get(filePath + collectionFileName);

        FileUtils.writeFile(reportingFile.toString(),messageList,"GBK");
    }

    @Override
    public void mergeFile(PrOrganizationTable org, String filePath, String nftsPath, String outPath) throws IOException {
        logger.info("开始合并分库文件");

        Date bussinessDate = org.getToday();
        String toDay = DateUtils.format(bussinessDate,"yyyyMMdd");
        String reportingPath = filePath + org.getTenantId() + File.separator + toDay + File.separator;
        String outFilePath = outPath + org.getTenantId() + File.separator + toDay + File.separator;

        String fileName = ReportingConstant.LS_BREAK_CONTRACT + ".dat";
        String okFileName = "JLCLOUD_" + toDay + ".ok";

        Path reportingFile = Paths.get(outFilePath + fileName);
        Path reportingokFile = Paths.get(outFilePath + okFileName);
        try {
            Files.deleteIfExists(reportingFile);
            Files.deleteIfExists(reportingokFile);
        } catch (IOException e) {
            logger.error("删除个人贷款违约文件失败",e);
        }

        Path pFile = Paths.get(outFilePath);

        if (!Files.isDirectory(pFile)) {
            //创建文件夹
            try {
                Files.createDirectories(pFile);
            } catch (IOException e) {
                logger.error("创建目录失败",e);
            }
        }

        //获取目录下所有文件
        File file = new File(reportingPath);
        File[] tempList = file.listFiles();
        if(tempList == null || tempList.length == 0){
            logger.error("文件合并，未获取到需要合并的文件");
            throw new RuntimeException("文件合并，未获取到需要合并的文件");
        }

        List<File> mergeList = new ArrayList<>();

        for(int i = 0; i < tempList.length; i++){
            String fileName1 = tempList[i].getName();
            if(ReportingConstant.LS_BREAK_CONTRACT.length()>fileName1.length()){
                continue;
            }
            String subStr = fileName1.substring(0,ReportingConstant.LS_BREAK_CONTRACT.length());
            if(ReportingConstant.LS_BREAK_CONTRACT.equals(subStr)){
                mergeList.add(tempList[i]);
            }
        }
        //合并文件
        File resultFile = new File(outFilePath + fileName);

        Boolean isNullFile = true;
        try(FileChannel resultFileChannel= new FileOutputStream(resultFile, true).getChannel()){
            for(int i = 0; i < mergeList.size(); i++){
                FileChannel blk1 = new FileInputStream(mergeList.get(i)).getChannel();
                if(i == 0 && blk1.size() == 0){
                    resultFile.createNewFile();
                }else if (blk1.size() != 0){
                    if(!isNullFile && i != 0){
                        //换行
                        ByteBuffer buf = ByteBuffer.allocate(48);
                        buf.clear();
                        buf.put("\r\n".getBytes());
                        buf.flip();
                        while(buf.hasRemaining()) {
                            resultFileChannel.write(buf);
                        }
                    }
                    //写入新文件
                    resultFileChannel.transferFrom(blk1, resultFileChannel.size(), blk1.size());
                    isNullFile = false;
                }
                blk1.close();
            }
        } catch (IOException e) {
            logger.error("临商个人违约文件合并异常，异常信息：",e);
            throw new RuntimeException(e);
        }

        //生成OK文件
        Path okFile = Paths.get(outFilePath + okFileName);
        try {
            Files.createFile(okFile);
        } catch (IOException e) {
            logger.error("创建临商OK失败",e);
            throw new RuntimeException("创建联盟OK失败");

        }

        //文件传输
        try {
            createTskdFileSampleSimple.initNfsTransFile(outFilePath, nftsPath, "", "s_anyrcs_cbrc" ,org.getTenantId(),toDay,"0");
        } catch (Exception e1) {
            logger.error("文件传输失败",e1);
            throw new RuntimeException("文件传输失败");
        }
    }


    private String transFive(String five){
        switch (five){
            case ReportingConstant.LOAN_CLASSIFY_0:
                return ReportingConstant.LS_CLASSIFY_1;
            case ReportingConstant.LOAN_CLASSIFY_1:
                return ReportingConstant.LS_CLASSIFY_2;
            case ReportingConstant.LOAN_CLASSIFY_2:
                return ReportingConstant.LS_CLASSIFY_3;
            case ReportingConstant.LOAN_CLASSIFY_3:
                return ReportingConstant.LS_CLASSIFY_4;
            default:
                return ReportingConstant.LS_CLASSIFY_5;
        }
    }
}
